home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / cmdity / yk212src.lha / Yak_2.12_Src / WBStartup / Unixdirs.c < prev    next >
C/C++ Source or Header  |  1996-03-02  |  16KB  |  575 lines

  1. /*
  2.  ** Patches dos.library functions to allow use of '.' and '..' ala UNIX.
  3.  ** Largely inspired from UnixDirsII from Martin Scott.
  4.  **
  5.  ** List of patched functions :
  6.  **
  7.  **     AssignLate
  8.  **     AssignPath
  9.  **     CreateDir
  10.  **     DeleteFile
  11.  **     LoadSeg
  12.  **     Lock
  13.  **     MakeLink
  14.  **     MatchFirst
  15.  **     NewLoadSeg
  16.  **     Open
  17.  **     ParsePattern
  18.  **     Rename
  19.  **     SetComment
  20.  **     SetFileDate
  21.  **     SetProtection
  22.  **
  23.  ** Author: Gael Marziou
  24.  ** Created: 14 July 94 (Bastille day ;-)
  25.  **
  26.  **
  27.  */
  28.  
  29. #define __USE_SYSBASE
  30.  
  31. #include <exec/types.h>
  32. #include <exec/execbase.h>
  33. #include <exec/memory.h>
  34. #include <exec/semaphores.h>
  35. #include <dos/dos.h>
  36. #include <libraries/commodities.h>
  37. #include <string.h>
  38. #include <proto/dos.h>
  39. #include <proto/exec.h>
  40.  
  41. #include "Patch_Libs.h"
  42. #include "yak.h"
  43. #include "Settings.h"
  44.  
  45. /* Local protos */
  46. SAVEDS BOOL adjustpath(UBYTE *path, UBYTE *newpath, LONG len);
  47.  
  48. /* The number of 'replacement' functions for UnixDirs feature */
  49. #define UNIXDIRS_NUMBEROFFUNCTIONS (15)
  50.  
  51. /* declare stuff for standard one-parameter function */
  52. /* UBYTE * in d1 */
  53. #define DEC11_OLD(oldname) LONG (*ASM oldname) (REG(d1) UBYTE *, REG(a6) struct Library *base)
  54. #define DEC11_NEW(newname) SAVEDS LONG ASM newname(REG(d1) UBYTE *, REG(a6) struct Library *base)
  55. #define DEC11(name) DEC11_OLD(old## name); DEC11_NEW(new## name); DEC_LVO(LVO## name)
  56.  
  57. /* declare stuff for standard two-parameter function */
  58. /* UBYTE * in d1 */
  59. #define DEC21_OLD(oldname) LONG (*ASM oldname) (REG(d1) UBYTE *, REG(d2) LONG, REG(a6) struct Library *base)
  60. #define DEC21_NEW(newname) SAVEDS LONG ASM newname(REG(d1) UBYTE *, REG(d2) LONG, REG(a6) struct Library *base)
  61. #define DEC21(name) DEC21_OLD(old## name); DEC21_NEW(new## name); DEC_LVO(LVO## name)
  62.  
  63. /* declare stuff for standard two-parameter function */
  64. /* UBYTE * in d2 */
  65. #define DEC22_OLD(oldname) LONG (*ASM oldname) (REG(d1) LONG, REG(d2) UBYTE *, REG(a6) struct Library *base)
  66. #define DEC22_NEW(newname) SAVEDS LONG ASM newname(REG(d1) LONG, REG(d2) UBYTE *, REG(a6) struct Library *base)
  67. #define DEC22(name) DEC22_OLD(old## name); DEC22_NEW(new## name); DEC_LVO(LVO## name)
  68.  
  69. /* the patched functions themselves */
  70. DEC22(AssignLate);
  71. DEC22(AssignPath);
  72. DEC11(CreateDir);
  73. DEC11(DeleteFile);
  74. DEC11(LoadSeg);
  75. DEC21(Lock);
  76. DEC21(MatchFirst);
  77. DEC21(NewLoadSeg);
  78. DEC21(Open);
  79. DEC21(SetComment);
  80. DEC21(SetFileDate);
  81. DEC21(SetProtection);
  82.  
  83.  
  84. /* manually declared, because different from standard */
  85.  
  86. LONG (*ASM oldMakeLink) (REG(d1) UBYTE *, REG(d2) LONG, REG(d3) LONG, REG(a6) struct Library *);
  87. SAVEDS LONG ASM newMakeLink(REG(d1) UBYTE *, REG(d2) LONG, REG(d3) LONG, REG(a6) struct Library *);
  88. extern LVOMakeLink;
  89.  
  90. LONG (*ASM oldRename) (REG(d1) UBYTE *, REG(d2) UBYTE *, REG(a6) struct Library *);
  91. SAVEDS LONG ASM newRename(REG(d1) UBYTE *, REG(d2) UBYTE *, REG(a6) struct Library *);
  92. extern LVORename;
  93.  
  94. LONG (*ASM oldParsePattern) (REG(d1) UBYTE *, REG(d2) UBYTE *, REG(d3) LONG, REG(a6) struct Library *);
  95. SAVEDS LONG ASM newParsePattern(REG(d1) UBYTE *, REG(d2) UBYTE *, REG(d3) LONG, REG(a6) struct Library *);
  96. extern LVOParsePattern;
  97.  
  98. struct LVOTable LVOArrayUnixDirs[] =
  99. {
  100. {(LONG)&LVOCreateDir, (struct Library *)&DOSBase, (ULONG)&oldCreateDir, (ULONG)&newCreateDir },
  101. {(LONG)&LVODeleteFile, (struct Library *)&DOSBase, (ULONG)&oldDeleteFile, (ULONG)&newDeleteFile },
  102. {(LONG)&LVOLoadSeg, (struct Library *)&DOSBase, (ULONG)&oldLoadSeg, (ULONG)&newLoadSeg },
  103.     
  104. {(LONG)&LVOLock, (struct Library *)&DOSBase, (ULONG)&oldLock, (ULONG)&newLock },
  105. {(LONG)&LVONewLoadSeg, (struct Library *)&DOSBase, (ULONG)&oldNewLoadSeg, (ULONG)&newNewLoadSeg },
  106. {(LONG)&LVOOpen, (struct Library *)&DOSBase, (ULONG)&oldOpen, (ULONG)&newOpen },
  107.     
  108. {(LONG)&LVOSetComment, (struct Library *)&DOSBase, (ULONG)&oldSetComment, (ULONG)&newSetComment },
  109. {(LONG)&LVOSetFileDate, (struct Library *)&DOSBase, (ULONG)&oldSetFileDate, (ULONG)&newSetFileDate },
  110.     
  111. {(LONG)&LVOSetProtection, (struct Library *)&DOSBase, (ULONG)&oldSetProtection, (ULONG)&newSetProtection },
  112. {(LONG)&LVOAssignLate, (struct Library *)&DOSBase, (ULONG)&oldAssignLate, (ULONG)&newAssignLate },
  113. {(LONG)&LVOAssignPath, (struct Library *)&DOSBase, (ULONG)&oldAssignPath, (ULONG)&newAssignPath },
  114. {(LONG)&LVORename, (struct Library *)&DOSBase, (ULONG)&oldRename, (ULONG)&newRename },
  115. {(LONG)&LVOMakeLink, (struct Library *)&DOSBase, (ULONG)&oldMakeLink, (ULONG)&newMakeLink },
  116. {(LONG)&LVOMatchFirst, (struct Library *) & DOSBase, (ULONG)&oldMatchFirst, (ULONG)&newMatchFirst },
  117. {(LONG)&LVOParsePattern, (struct Library *) & DOSBase, (ULONG)&oldParsePattern, (ULONG)&newParsePattern }
  118. };
  119.  
  120.  
  121. struct UnixDirsJumpTable
  122. {
  123.     struct SignalSemaphore jt_Semaphore;
  124.     UWORD pad_word;
  125.     struct Task *jt_Owner;
  126.     UBYTE jt_Function[UNIXDIRS_NUMBEROFFUNCTIONS * 6];
  127. };
  128.  
  129. /* Strings */
  130. /* The name this JumpTable/Semaphore will get. */
  131. static UBYTE *UnixDirsJTName = "YakUnixDirs-JT";
  132.  
  133. static BOOL UnixDirsPatchInstalled = FALSE;
  134.  
  135.  
  136. __regargs void
  137.     ToggleUnixDirs( BOOL toggle )
  138. {
  139.     if (toggle == TRUE)
  140.     {
  141.         if (UnixDirsPatchInstalled == FALSE)
  142.         {
  143.             InstallWedge(UnixDirsJTName, 
  144.                          LVOArrayUnixDirs, 
  145.                          (UBYTE) UNIXDIRS_NUMBEROFFUNCTIONS);
  146.             UnixDirsPatchInstalled = TRUE;
  147.         }
  148.     }
  149.     else
  150.     {
  151.         if (UnixDirsPatchInstalled == TRUE)
  152.         {
  153.             RemoveWedge(UnixDirsJTName, 
  154.                         LVOArrayUnixDirs, 
  155.                         (UBYTE) UNIXDIRS_NUMBEROFFUNCTIONS);
  156.             UnixDirsPatchInstalled = FALSE;
  157.         }
  158.     }
  159. }
  160.  
  161.  
  162. /******************************************************************************/
  163. /*******************                                 **************************/
  164. /*******************   NEW DOS ROUTINES START HERE   **************************/
  165. /*******************                                 **************************/
  166. /******************************************************************************/
  167.  
  168. /********************************************
  169.   
  170.   Example of the simplest patch (does nothing)
  171.   
  172.   SAVEDS LONG ASM
  173.   new(REG(d1) LONG arg1, REG(d2) LONG arg2,
  174.   REG(a6) struct Library *base)
  175.   {
  176.   return old(arg1, arg2, base);
  177.   }
  178.   
  179.   ********************************************/
  180.  
  181. /*
  182.  * These are the generic patch routines.
  183.  * They handle most patches automatically.
  184.  */
  185.  
  186. #define PATHSIZE    512L    /* enough for most purposes? */
  187.  
  188. /* 1 args, convert arg in d1 */
  189. LONG ASM Wedge11 (REG(a0) LONG (*ASM dosroutine)(REG(d1) UBYTE *, REG(a6) struct Library *),
  190.                   REG(d1) UBYTE *arg1, 
  191.                   REG(a6) struct Library *base)
  192. {
  193.    struct SignalSemaphore *jt;
  194.    UBYTE *newpath;
  195.    LONG rc = 0;
  196.     
  197.    if (jt = FindSemaphore(UnixDirsJTName))
  198.    {
  199.       ObtainSemaphoreShared(jt);
  200.         
  201.       if (newpath = AllocVec(PATHSIZE, 0L))
  202.       {
  203.          if (adjustpath(arg1, newpath, PATHSIZE))
  204.          {
  205.             rc = dosroutine(newpath, base);
  206.  
  207.             if ((rc == 0) && slashdir && (arg1[0] == '/'))
  208.             {
  209.                /* in case it failed with slashdir try a normal amigados path */
  210.                newpath[0]='/';   
  211.                rc = dosroutine(newpath, base);
  212.             }
  213.          }
  214.          else
  215.          {
  216.             rc = dosroutine(arg1, base);
  217.          }
  218.          FreeVec(newpath);
  219.       }
  220.       else SetIoErr(ERROR_NO_FREE_STORE);
  221.         
  222.       ReleaseSemaphore(jt);
  223.    }
  224.    return rc;
  225. }
  226.  
  227. /* 2 args, convert arg in d1 */
  228. LONG ASM Wedge21 (REG(a0) LONG (*ASM dosroutine)(REG(d1) UBYTE *, REG(d2) LONG, REG(a6) struct Library *),
  229.                   REG(d1) UBYTE *arg1,
  230.                   REG(d2) LONG arg2, 
  231.                   REG(a6) struct Library *base)
  232. {
  233.    struct SignalSemaphore *jt;
  234.    UBYTE *newpath;
  235.    LONG rc = 0;
  236.     
  237.    if (jt = FindSemaphore(UnixDirsJTName))
  238.    {
  239.       ObtainSemaphoreShared(jt);
  240.         
  241.       if (newpath = AllocVec(PATHSIZE, 0L))
  242.       {
  243.          if (adjustpath(arg1, newpath, PATHSIZE))
  244.          {
  245.             rc = dosroutine(newpath, arg2, base);
  246.  
  247.             if ((rc == 0) && slashdir && (arg1[0] == '/'))
  248.             {
  249.                /* in case it failed with slashdir try a normal amigados path */
  250.                newpath[0]='/';   
  251.                rc = dosroutine(newpath, arg2, base);
  252.             }
  253.          }
  254.          else
  255.          {
  256.             rc = dosroutine(arg1, arg2, base);
  257.          }
  258.          FreeVec(newpath);
  259.       }
  260.       else SetIoErr(ERROR_NO_FREE_STORE);
  261.         
  262.       ReleaseSemaphore(jt);
  263.    }
  264.    return rc;
  265. }
  266.  
  267. /* 2 args, convert arg in d2 */
  268.  
  269. LONG ASM Wedge22 (REG(a0) LONG (*ASM dosroutine)(REG(d1) LONG, REG(d2) UBYTE *, REG(a6) struct Library *),
  270.                   REG(d1) LONG arg1,
  271.                   REG(d2) UBYTE *arg2, 
  272.                   REG(a6) struct Library *base)
  273. {
  274.    struct SignalSemaphore *jt;
  275.    UBYTE *newpath;
  276.    LONG rc = 0;
  277.     
  278.    if (jt = FindSemaphore(UnixDirsJTName))
  279.    {
  280.       ObtainSemaphoreShared(jt);
  281.         
  282.       if (newpath = AllocVec(PATHSIZE, 0L))
  283.       {
  284.          if (adjustpath(arg2, newpath, PATHSIZE))
  285.          {
  286.             rc = dosroutine(arg1, newpath, base);
  287.  
  288.             if ((rc == 0) && slashdir && (arg2[0] == '/'))
  289.             {
  290.                /* in case it failed with slashdir try a normal amigados path */
  291.                newpath[0]='/';   
  292.                rc = dosroutine(arg1, newpath, base);
  293.             }
  294.          }
  295.          else
  296.          {
  297.             rc = dosroutine(arg1, arg2, base);
  298.          }
  299.             
  300.          FreeVec(newpath);
  301.       }
  302.       else SetIoErr(ERROR_NO_FREE_STORE);
  303.         
  304.       ReleaseSemaphore(jt);
  305.    }
  306.    return rc;
  307. }
  308.  
  309. #define PATCH11(name) \
  310.     SAVEDS LONG ASM \
  311.     new## name(REG(d1) UBYTE *arg1, \
  312.                REG(a6) struct Library *base) \
  313. { return Wedge11(old## name, arg1, base); }
  314.  
  315. #define PATCH21(name) \
  316.     SAVEDS LONG ASM \
  317.     new## name(REG(d1) UBYTE *arg1, REG(d2) LONG arg2, \
  318.                REG(a6) struct Library *base) \
  319. { return Wedge21(old## name, arg1, arg2, base); }
  320.  
  321. #define PATCH22(name) \
  322.     SAVEDS LONG ASM \
  323.     new## name(REG(d1) LONG arg1, REG(d2) UBYTE *arg2, \
  324.                REG(a6) struct Library *base) \
  325. { return Wedge22(old## name, arg1, arg2, base); }
  326.  
  327. PATCH22(AssignLate)
  328. PATCH22(AssignPath)
  329. PATCH11(CreateDir)
  330. PATCH11(DeleteFile)
  331. PATCH11(LoadSeg)
  332. PATCH21(Lock)
  333. PATCH21(MatchFirst)
  334. PATCH21(NewLoadSeg)
  335. PATCH21(Open)
  336. PATCH21(SetComment)
  337. PATCH21(SetFileDate)
  338. PATCH21(SetProtection)
  339.  
  340. /*** And the following routines are handmade ***/
  341.  
  342. SAVEDS LONG ASM
  343.     newRename(REG(d1) UBYTE *oldname, REG(d2) UBYTE *newname,
  344.               REG(a6) struct Library *base)
  345. {
  346.    struct SignalSemaphore *jt;
  347.    UBYTE *from, *to;
  348.    LONG rc = 0;
  349.     
  350.    if (jt = FindSemaphore(UnixDirsJTName))
  351.    {
  352.       ObtainSemaphoreShared(jt);
  353.         
  354.       if (from = AllocVec(PATHSIZE, 0L))
  355.       {
  356.          adjustpath(oldname, from, PATHSIZE);
  357.          if (to = AllocVec(PATHSIZE, 0L))
  358.          {
  359.             adjustpath(newname, to, PATHSIZE);
  360.             rc = oldRename(from, to, base);
  361.             if ((rc == 0) && slashdir)
  362.             {
  363.                BOOL Retry = FALSE;
  364.  
  365.                if (oldname[0] == '/')
  366.                {
  367.                   /* in case it failed with slashdir try a normal amigados path */
  368.                   from[0]='/'; 
  369.                   Retry = TRUE;
  370.                }  
  371.                if (newname[0] == '/')
  372.                {
  373.                   /* in case it failed with slashdir try a normal amigados path */
  374.                   to[0]='/'; 
  375.                   Retry = TRUE;
  376.                 }  
  377.                if (Retry == TRUE)
  378.                {
  379.                   rc = oldRename(from, to, base);
  380.                }
  381.             }
  382.             FreeVec(to);
  383.          }
  384.          else SetIoErr(ERROR_NO_FREE_STORE);
  385.          FreeVec(from);
  386.       }
  387.       else SetIoErr(ERROR_NO_FREE_STORE);
  388.         
  389.       ReleaseSemaphore(jt);
  390.    }
  391.    return rc;
  392. }
  393.  
  394.  
  395. /* a bit more suspect this; will buflen be big enough given a . substitution? */
  396. SAVEDS LONG ASM
  397.     newParsePattern(REG(d1) UBYTE *pat, 
  398.                     REG(d2) UBYTE *buf, 
  399.                     REG(d3) LONG buflen,
  400.                     REG(a6) struct Library *base)
  401. {
  402.    struct SignalSemaphore *jt;
  403.    UBYTE *newpat;
  404.    LONG rc = 0;
  405.     
  406.    if (jt = FindSemaphore(UnixDirsJTName))
  407.    {
  408.       ObtainSemaphoreShared(jt);
  409.         
  410.       if (newpat = AllocVec(PATHSIZE, 0L))
  411.       {
  412.          adjustpath(pat, newpat, PATHSIZE);
  413.          rc = oldParsePattern(newpat, buf, buflen, base);
  414.          FreeVec(newpat);
  415.       }
  416.       else SetIoErr(ERROR_NO_FREE_STORE);
  417.         
  418.       ReleaseSemaphore(jt);
  419.    }
  420.    return rc;
  421. }
  422.  
  423.  
  424. SAVEDS LONG ASM
  425.     newMakeLink (REG(d1) UBYTE *name, 
  426.                  REG(d2) LONG dest,
  427.                  REG(d3) LONG soft,
  428.                  REG(a6) struct Library *base)
  429. {
  430.    struct SignalSemaphore *jt;
  431.    UBYTE *from, *to;
  432.    LONG rc = 0;
  433.     
  434.    if (jt = FindSemaphore(UnixDirsJTName))
  435.    {
  436.       ObtainSemaphoreShared(jt);
  437.         
  438.       if (from = AllocVec(PATHSIZE, 0L))
  439.       {
  440.          adjustpath(name, from, PATHSIZE);
  441.          if (soft)
  442.          {
  443.             /* dest points to a null-terminated path string */
  444.             if (to = AllocVec(PATHSIZE, 0L))
  445.             {
  446.                adjustpath((STRPTR)dest, to, PATHSIZE);
  447.                rc = oldMakeLink(from, (LONG)to, soft, base);
  448.                FreeVec(to);
  449.             }
  450.             else SetIoErr(ERROR_NO_FREE_STORE);
  451.          }
  452.          else
  453.          {
  454.             /* dest is a lock (BPTR) */
  455.             rc = oldMakeLink(from, dest, soft, base);
  456.          }
  457.          FreeVec(from);
  458.       }
  459.       else SetIoErr(ERROR_NO_FREE_STORE);
  460.         
  461.       ReleaseSemaphore(jt);
  462.    }
  463.    return rc;
  464. }
  465.  
  466.  
  467.  
  468.  
  469. /*
  470.  * Routine to convert a UNIX-style path to an AmigaDOS path.
  471.  * A UNIX-style path is understood here as follows:
  472.  * 
  473.  *  leading . means current dir; like "", but filled in explicitly
  474.  *  ../ means /
  475.  *  ..  means /
  476.  * 
  477.  * Written as part of UnixDirs2, a (to be written) system patch which allows
  478.  * use of UNIX-style paths everywhere.
  479.  * 
  480.  * Martin W. Scott,  8 January 1993
  481.  */
  482.  
  483.  
  484. /* insert $cwd into s, return pointer to next free char */
  485. SAVEDS char *
  486.     insertcwd(char *s, LONG len)
  487. {
  488.    if (NameFromLock(((struct Process *)(((struct ExecBase *)SysBase)->ThisTask))->pr_CurrentDir, s, len))
  489.    {
  490.       while (*s)
  491.          s++;
  492.    }
  493.    return s;
  494. }
  495.  
  496. /* adjust path from UNIX-style to Amiga-style */
  497. /* TO DO: length checking when building new path */
  498.  
  499. SAVEDS BOOL
  500.     adjustpath(UBYTE *path, UBYTE *newpath, LONG len)
  501. {
  502.    UBYTE *s, *t;
  503.    char *origpath = path;
  504.     
  505.    s = newpath;
  506.     
  507.    if (path == NULL)            /* bypass */
  508.       return FALSE;
  509.     
  510.    if (slashdir && (path[0] == '/'))
  511.    {
  512.       s[0]=':';                 /* to accommodate unix-style root paths */
  513.       path++;
  514.       s++;
  515.    }
  516.  
  517.    if (t = strchr(path, ':'))   /* check for ':' in path */
  518.    {
  519.       t++;                      /* copy device component */
  520.       while (path < t)
  521.          *s++ = *path++;
  522.    }
  523.    else if (path[0] == '.')     /*** translate '.' to $cwd ***/
  524.    {
  525.       if (!path[1])             /* only "." */
  526.       {
  527.          s = insertcwd(s, len);
  528.          path++;                /* path[0] == '\0' - STOP */
  529.       }
  530.       else if (path[1] == '/')  /* initial component is $cwd */
  531.       {
  532.          s = insertcwd(s, len);
  533.          if (*(s-1) != ':')
  534.             *s++ = '/';         /* copy '/', increment pointers */
  535.          path += 2;
  536.       }
  537.    }
  538.     
  539.    while (path[0])              /*** copy remainder of path ***/
  540.    {
  541.       if ((path[0] == '.') && (path[1] == '.'))
  542.       {
  543.          if (path[2] == '/')    /* just skip "..", copying '/' */
  544.          {
  545.             path += 2;
  546.             *s++ = *path++;
  547.          }
  548.          else if (!path[2] )    /* append '/' and stop */
  549.          {
  550.             if ((path == origpath) ||
  551.                 (*(path-1) == '/') ||
  552.                 (*(path-1) == ':'))
  553.             {
  554.                path += 2;
  555.                *s++ = '/';
  556.             }
  557.             else 
  558.             {
  559.                *s++ = *path++;
  560.                *s++ = *path++;
  561.             }
  562.          }
  563.          else *s++ = *path++;
  564.       }
  565.       else *s++ = *path++;
  566.    }
  567.    *s = '\0';
  568.     
  569.    return TRUE;
  570. }
  571.  
  572.  
  573.  
  574.  
  575.